﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using LitJson;
using System.IO;
using Framework.AssetsManager;
using System.Text;

public class ProcUpdate : Proc
{
    public ProcUpdate()
        : base(ProcType.PROC_UPDATE)
    {

    }


    public override void process()
    {

    }

    public override void onBegin(object[] param)
    {
#if NO_UPDATE 
        onLoadFinish(true);
#else
        Mainloop.Instance.StartCoroutine(UpdateAssets());
#endif

        IsInit = true;
    }

    public override void onEnd()
    {

    }

    string m_wwwVersion;
    private int m_wwwAppVersion = 0;
    private int m_wwwAssetsVersion = 0;
    private string m_assetsListPath = "";
    private string m_assetsMD5Path = "";

    private IEnumerator UpdateAssets()
    {
        yield return new WaitForEndOfFrame();
        TextAsset text;
        
        //1读cdn上面的版本号
        TextAsset content = Resources.Load(AssetsMgtConst.AssetsFileName) as TextAsset;
        string localAssetsList = content.text;
        string versionUrl = "http://shipwarversion.luhanzju.win:9280/version/find";

        WWW wwwVersionRequest = new WWW(versionUrl);
        yield return wwwVersionRequest;

        m_wwwVersion = wwwVersionRequest.text;
        JsonData wwwVersionData = JsonMapper.ToObject(m_wwwVersion);

        m_wwwAppVersion = (int)wwwVersionData[AssetsMgtConst.AppVersion];
        m_wwwAssetsVersion = (int)wwwVersionData[AssetsMgtConst.AssetsVersion];
        m_assetsListPath = (string)wwwVersionData[AssetsMgtConst.AssetsListPath];
        m_assetsMD5Path = (string)wwwVersionData[AssetsMgtConst.AssetsMD5Path];
        wwwVersionRequest.Dispose();

        //2读本地的版本号
        yield return new WaitForEndOfFrame();
        string localFilePath = Application.persistentDataPath + "/res" + AssetsMgtConst.CurrentVersion + "/" + AssetsMgtConst.Version;
        FileInfo info = new FileInfo(localFilePath);
        JsonData localVersionData = null;
        if (info.Exists)
        {
            StreamReader sr = File.OpenText(localFilePath);
            string localFileText = sr.ReadToEnd();
            localVersionData = JsonMapper.ToObject(localFileText);
            sr.Close();
            sr.Dispose();
        }
        else
        {
            text = (TextAsset)Resources.Load(AssetsMgtConst.VersionName);
            if (text == null)
            {
                Debug.LogWarning("Resource doesn't has version.txt");
                yield break;
            }

            localVersionData = JsonMapper.ToObject(text.text);
        }
        AssetsMgtConst.CurrentVersion = (int)localVersionData[AssetsMgtConst.AppVersion];
        if (m_wwwAppVersion != AssetsMgtConst.CurrentVersion)
        {
            //主版本要更新了，不能让玩家接着玩儿了
            yield break;
        }

        //3读Resource里面的文件列表
        yield return new WaitForEndOfFrame();
        text = (TextAsset)Resources.Load(AssetsMgtConst.AssetsFileName);
        JsonData jsonData = JsonMapper.ToObject(text.text);
        for (int i = 0; i < jsonData.Count; i++)
        {
            AssetData template = new AssetData();
            template.name = (string)jsonData[i]["Name"];
            template.version = (int)jsonData[i]["Version"];
            template.size = (int)jsonData[i]["Size"];
            template.type = (EResType)(int)jsonData[i]["Type"];
            template.loadType = (ELoadTaskType)(int)jsonData[i]["LoadType"];
            template.path = (string)jsonData[i]["Path"];
            template.whenLoad = (EResWhenLoad)(int)jsonData[i]["WhenLoad"];

            AssetDataManager.Instance.AddAssetData(template.name, template);

        }

        //4.读本地保存的文件列表
        yield return new WaitForEndOfFrame();
        string lastFile = Application.persistentDataPath + "/res" + AssetsMgtConst.CurrentVersion + "/" + AssetsMgtConst.LastAssetsListName;
        info = new FileInfo(lastFile);

        if (info.Exists)
        {
            string localAssetListTxt = ReadFile(lastFile);
            JsonData LocalAssetList = JsonMapper.ToObject(localAssetListTxt);
            for (int i = 0; i < LocalAssetList.Count; i++)
            {
                string name = (string)LocalAssetList[i]["Name"];
                int version = (int)LocalAssetList[i]["Version"];
                AssetData localData = AssetDataManager.Instance.GetAssetData(name);
                if (localData == null || localData.version < version)
                {
                    JsonData jsonAsset = LocalAssetList[i];
                    AssetData template = new AssetData();
                    template.name = (string)jsonAsset["Name"];
                    template.version = (int)jsonAsset["Version"];
                    template.size = (int)jsonAsset["Size"];
                    template.type = (EResType)(int)jsonAsset["Type"];
                    template.loadType = (ELoadTaskType)(int)jsonAsset["LoadType"];
                    template.path = (string)jsonAsset["Path"];
                    template.whenLoad = (EResWhenLoad)(int)jsonAsset["WhenLoad"];

                    AssetDataManager.Instance.AddAssetData(name, template);
                }
            }
        }

        //5.读cdn上面的文件列表
        yield return new WaitForEndOfFrame();
        WWW assetWWW = new WWW(m_assetsListPath);//这里只要调用一次就会缓存
        yield return assetWWW;

        if (assetWWW.error != null)
        {
            Debug.Log(assetWWW.error + "(" + m_assetsListPath + ")");
            yield break;
        }

        string assetsListCsv = assetWWW.text;
        JsonData serverAssetList = JsonMapper.ToObject(assetsListCsv);

        float downloadSize = 0;
        List<AssetData> updateItems = new List<AssetData>();
        for (int i = 0; i < serverAssetList.Count; i++)
        {
            string name = (string)serverAssetList[i]["Name"];
            int version = (int)serverAssetList[i]["Version"];
            AssetData localData = AssetDataManager.Instance.GetAssetData(name);
            if (localData == null || localData.version < version)
            {
                jsonData = serverAssetList[i];
                AssetData updateData = new AssetData();
                updateData.name = (string)jsonData["Name"];
                updateData.version = (int)jsonData["Version"];
                updateData.size = (int)jsonData["Size"];
                updateData.type = (EResType)(int)jsonData["Type"];
                updateData.loadType = (ELoadTaskType)(int)jsonData["LoadType"];
                updateData.path = (string)jsonData["Path"];
                updateData.whenLoad = (EResWhenLoad)(int)jsonData["WhenLoad"];

                AssetDataManager.Instance.AddAssetData(name, updateData);

                if (updateData.loadType == ELoadTaskType.WEB)
                {
                    updateItems.Add(updateData);
                    downloadSize += updateData.size;
                }
            }
        }
        assetWWW.Dispose();

        //6.如果有更新进行下载
        yield return new WaitForEndOfFrame();
        if (updateItems.Count > 0)
        {
            Mainloop.Instance.StartCoroutine(DoDownloadAssets(updateItems));
        }
        else
        {
            onLoadFinish(true);
        }
    }

    IEnumerator DoDownloadAssets(List<AssetData> updateItems)
    {
        WWW md5WWW = new WWW(m_assetsMD5Path);
        yield return md5WWW;
        if (md5WWW.error != null)
        {
            Debug.Log(md5WWW.error + "(" + m_assetsMD5Path + ")");
            yield break;
        }
        string assetsMd5 = md5WWW.text;
        JsonData assetsMD5List = JsonMapper.ToObject(assetsMd5);
        Dictionary<string, string> assetsMD5Dict = new Dictionary<string, string>();
        for (int i = 0; i < assetsMD5List.Count; i++)
        {
            assetsMD5Dict.Add((string)assetsMD5List[i]["Name"], (string)assetsMD5List[i]["MD5"]);
        }

        foreach (var updateItem in updateItems)
        {
            updateItem.MD5 = assetsMD5Dict[updateItem.name];
            LoadModule.Instance.AddTask(updateItem);
        }

        LoadModule.Instance.StartLoadTasks(onLoadFinish);
    }

    private void SaveAssetsFile()
    {
        string localFile = "";
        if (!string.IsNullOrEmpty(m_wwwVersion))
        {
            localFile = Application.persistentDataPath + "/res" + AssetsMgtConst.CurrentVersion + "/" + AssetsMgtConst.Version;
            SaveFile(localFile, m_wwwVersion);
        }

        StringBuilder sb = new StringBuilder();
        JsonWriter jsonWriter = new JsonWriter(sb);
        jsonWriter.WriteArrayStart();
        foreach(var item in AssetDataManager.Instance.GetAllDatas())
        {
            jsonWriter.WriteObjectStart();
            string name = item.Key;
            AssetData asset = item.Value;
            jsonWriter.WritePropertyName("Name");
            jsonWriter.Write(asset.name);
            jsonWriter.WritePropertyName("Version");
            jsonWriter.Write(asset.version);
            jsonWriter.WritePropertyName("Size");
            jsonWriter.Write(asset.size);
            jsonWriter.WritePropertyName("Type");
            jsonWriter.Write((int)asset.type);
            jsonWriter.WritePropertyName("LoadType");
            jsonWriter.Write((int)asset.loadType);
            jsonWriter.WritePropertyName("Path");
            jsonWriter.Write(asset.path);
            jsonWriter.WritePropertyName("WhenLoad");
            jsonWriter.Write((int)asset.whenLoad);
            jsonWriter.WriteObjectEnd();
        }
        jsonWriter.WriteArrayEnd();

        localFile = Application.persistentDataPath + "/res" + AssetsMgtConst.CurrentVersion + "/" + AssetsMgtConst.LastAssetsListName;
        SaveFile(localFile, sb.ToString());
    }

    private void onLoadFinish(bool _success)
    {
        if (_success)
        {
#if !NO_UPDATE
            Debug.Log("update Finish");

            SaveAssetsFile();

            var mustFirstLoad = AssetDataManager.Instance.GetDatasByWhenLoad(EResWhenLoad.MUST_FIRST_LOADED);
            while (mustFirstLoad.MoveNext())
            {
                RM.Instance.GetResource(mustFirstLoad.Current.name);
            }

            Mainloop.Instance.AppVersion = m_wwwAppVersion.ToString() + "." + m_wwwAssetsVersion;
#endif
            Mainloop.Instance.ctrl.changeProc(ProcType.PROC_SDK);
        }
        else
        {
            Debug.LogError("update Failed");
        }

    }

    private string ReadFile(string _path)
    {
        var utf8 = new System.Text.UTF8Encoding(true);

        StreamReader sr = new StreamReader(_path, utf8);
        string text = sr.ReadToEnd();
        sr.Close();

        return text;

    }


    private void SaveFile(string _file, string _content)
    {
        FileInfo info = new FileInfo(_file);
        if (info.Exists)
            File.Delete(_file);
        StreamWriter sw = info.CreateText();
        sw.WriteLine(_content);
        sw.Close();
        sw.Dispose();

    }

    public override void onTcpDisconnected()
    {
    }
}